package com.corpgovernment.permission.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.corpgovernment.api.organization.bo.RecManagerBO;
import com.corpgovernment.api.organization.bo.SearchRecManagerRequestBO;
import com.corpgovernment.api.organization.bo.SearchRecManagerResponseBO;
import com.corpgovernment.api.organization.model.enums.WholeGroupQueryEnum;
import com.corpgovernment.api.organization.model.org.OrgInfoVo;
import com.corpgovernment.api.organization.vo.DownloadRoleInfoRequest;
import com.corpgovernment.api.permission.soa.IUserPermissionClient;
import com.corpgovernment.api.permission.vo.UserMenuTo;
import com.corpgovernment.api.supplier.permission.vo.RoleDetailResponse;
import com.corpgovernment.common.apollo.OrganizationApollo;
import com.corpgovernment.common.base.BaseUserInfo;
import com.corpgovernment.common.base.JSONResult;
import com.corpgovernment.common.base.ResourceInfo;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.entity.db.BaseEntity;
import com.corpgovernment.common.enums.ExceptionCodeEnum;
import com.corpgovernment.common.enums.ResourceEnum;
import com.corpgovernment.common.operatelog.OperateLog;
import com.corpgovernment.common.operatelog.constant.OperateLogContant;
import com.corpgovernment.common.utils.BaseUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.organization.controller.OrganizationController;
import com.corpgovernment.organization.convert.EmployeeInfoConvert;
import com.corpgovernment.organization.dto.UserEmailDTO;
import com.corpgovernment.organization.entity.db.MbOrgEmployeeInfo;
import com.corpgovernment.organization.entity.db.MbOrgInfo;
import com.corpgovernment.organization.enumm.ExcelPostEnum;
import com.corpgovernment.organization.service.IOrganizationEmployeeService;
import com.corpgovernment.organization.service.IOrganizationInfoService;
import com.corpgovernment.organization.util.ExcelUtils;
import com.corpgovernment.organization.vo.ExcelCreateVO;
import com.corpgovernment.permission.config.RoleResourceManagerExt;
import com.corpgovernment.permission.entity.db.MbRole;
import com.corpgovernment.permission.entity.db.MbRolePermission;
import com.corpgovernment.permission.entity.db.MbRoleResource;
import com.corpgovernment.permission.entity.db.MbUserRole;
import com.corpgovernment.permission.service.*;
import com.corpgovernment.permission.vo.*;
import com.corpgovernment.redis.cache.RoleResourceManager;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.annotations.ApiOperation;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.BooleanUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/role")
@Slf4j
public class RoleRest {

    @Autowired
    private RoleService roleService;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private RolePermissionService rolePermissionService;
    @Autowired
    private IOrganizationInfoService organizationInfoService;
    @Autowired
    private IOrganizationEmployeeService organizationEmployeeService;
    @Autowired
    private MbRoleResourceService mbRoleResourceService;
    @Autowired
    private OrganizationController organizationController;
    @Autowired
    private ExcelUtils excelUtils;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private UserService userSrv;
    @Autowired
    private EmployeeInfoConvert employeeInfoConvert;
    @Autowired
    private RoleResourceManager manager;
    @Autowired
    private IUserPermissionClient permissionClient;
    @Autowired
    private OrganizationApollo organizationApollo;
    @Autowired
    private RoleResourceService roleResourceService;
    @Autowired
    private RoleResourceManagerExt roleResourceManagerExt;

    /**
     * url: /corpApi/organization/role/list http://10.5.119.87:9526/project/494/interface/api/11804
     */
    @PostMapping("/list")
    public JSONResult<List<RoleInfo>> listRole(@RequestBody ListRoleReq req, BaseUserInfo bui) {
        boolean findWholeGroup = WholeGroupQueryEnum.APPROVE.getCode().equals(req.getWholeGroupQuery())
                && organizationApollo.enableApproveShowAllOrg();
        if (findWholeGroup ||
                (bui.getBgUser() && BooleanUtils.isTrue(req.getIsBackground()))) {
            List<UserRole> userRoles = null;
            if(findWholeGroup){ // 查询全部角色
                // 查询所有组织结构
                List<MbOrgInfo> mbOrgInfoList = organizationInfoService.listAll();
                // 顶级集团数据
//                List<MbOrgInfo> topLevelList = mbOrgInfoList.stream().filter(m -> m.getLevel() == 1).collect(Collectors.toList());
                List<String> corpIdList = mbOrgInfoList.stream().filter(m->"C".equals(m.getOrgType())).map(MbOrgInfo::getOrgId).collect(Collectors.toList());
                List<RoleInfo> roleResultList = this.getRoleInfos(corpIdList);
                return JSONResult.success(roleResultList);
            }else{
                userRoles = userRoleService.listBgRole(null);
            }
            List<RoleInfo> userRolesNew = userRoles.stream().collect(Collectors.groupingBy(UserRole::getRoleId)).values().stream().map(urList -> {
                RoleInfo r = new RoleInfo();
                r.setUserCount((int) urList.stream().filter(ur -> new Date(0).equals(ur.getEmpDeleteTime())).filter(ur -> StringUtils.isNotBlank(ur.getUserId())).count());
                r.setName(urList.get(0).getRoleName());
                r.setIsRecManager(urList.get(0).getIsRecManager());
                r.setId(urList.get(0).getRoleId());
                r.setDataChangeTime(urList.get(0).getDataChangeTime());
                return r;
            }).sorted((r1, r2) -> -Comparator.comparing(RoleInfo::getDataChangeTime).compare(r1, r2))
                    .collect(Collectors.toList());
            return JSONResult.success(userRolesNew);
        } else {

            if (StringUtils.isNotBlank(req.getCorpId())){
                MbOrgInfo mbOrgInfo = organizationInfoService.findRecentCompanyIdByOrgId(req.getCorpId());
                req.setCorpId(mbOrgInfo.getOrgId());
            }

            List<MbOrgInfo> mbOrgInfos = organizationInfoService.listAll();

            List<MbOrgInfo> corpOrgList = mbOrgInfos.stream().filter(item -> Objects.equals("C", item.getOrgType())).collect(Collectors.toList());

            List<String> corpIdList = new ArrayList<>();
            if (StringUtils.isNotBlank(req.getCorpId())) {
                corpIdList.add(req.getCorpId());
            } else {
                corpIdList = corpOrgList.stream().map(MbOrgInfo::getOrgId).collect(Collectors.toList());
            }

            List<RoleInfo> roleResultList = this.getRoleInfos(corpIdList);
            return JSONResult.success(roleResultList);
        }


    }

    /**
     * 根据orgId获取角色信息
     * @param corpIdList
     * @return
     */
    private List<RoleInfo> getRoleInfos(List<String> corpIdList) {
        List<RoleInfo> roleResultList = new ArrayList<>();
        if(CollectionUtil.isEmpty(corpIdList)){
            return roleResultList;
        }
        for (String corpId : corpIdList) {
            MbOrgInfo orgInfo = organizationInfoService.findByOrgId(corpId);
            //根据公司ID查询下面的角色列表
            List<MbRole> roleList = Optional.ofNullable(roleService.listCorpRoles(corpId)).orElse(new ArrayList<>());
            //取出角色列表的ID集合
            List<Long> roleIdList = roleList.stream().map(BaseEntity::getId).collect(Collectors.toList());
            //根据角色ID查出用户与角色的关联关系
            List<MbUserRole> userRoleList = Optional.ofNullable(userRoleService.listByRoleIdList(roleIdList)).orElse(new ArrayList<>());
            //取出用户ID集合
            //List<String> uidList = userRoleList.stream().map(MbUserRole::getUid).collect(Collectors.toList());
            //合并分组 一个角色 -> 用户ID集合 Map<roleId, List<uid>>
            Map<Long, List<String>> roleUidMap = userRoleList.stream().collect(Collectors.groupingBy(MbUserRole::getRoleId, Collectors.mapping(MbUserRole::getUid, Collectors.toList())));
            //根据UID查询出用户详细信息
            //List<MbOrgEmployeeInfo> orgEmployeeInfoList = Optional.ofNullable(organizationEmployeeService.listByUids(uidList)).orElse(new ArrayList<>());
            //查询出来的UID集合 没查询出来说明可能离职删除了
            //List<String> validUidList = orgEmployeeInfoList.stream().map(MbOrgEmployeeInfo::getUid).collect(Collectors.toList());
            //数据组装
            List<RoleInfo> roleInfoList = roleList.stream()
                    .map(role -> {
                        RoleInfo target = new RoleInfo();
                        Long roleId = role.getId();
                        List<String> subUidList = roleUidMap.getOrDefault(roleId, new ArrayList<>());
                        target.setUserCount(subUidList.size());
                        target.setName(role.getName());
                        target.setIsRecManager(role.getIsRecManager());
                        target.setId(roleId);
                        target.setDataChangeTime(role.getDatachangeLasttime());
                        target.setLevel(role.getLevel());
                        target.setParentId(role.getParentId());
                        return target;
                    })
                    .sorted((r1, r2) -> Comparator.comparing(RoleInfo::getDataChangeTime).compare(r2, r1))
                    .collect(Collectors.toList());

            List<RoleInfo> newRoleInfo = roleInfoList.stream().filter(item -> Objects.equals(item.getLevel(), 1)).collect(Collectors.toList());

            Map<Long, List<RoleInfo>> parentMap = roleInfoList.stream().filter(item -> Objects.nonNull(item.getParentId()) && item.getParentId() > 0).collect(Collectors.groupingBy(RoleInfo::getParentId));

            //目前只有二级 直接塞不用递归
            newRoleInfo.forEach(item -> {
                List<RoleInfo> roleInfos = parentMap.get(item.getId());
                if (!CollectionUtils.isEmpty(roleInfos)) {
                    BigDecimal reduce = roleInfos.stream().map(RoleInfo::getUserCount).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add);
                    item.setUserCount(reduce.intValue() + item.getUserCount());
                    item.setChildren(roleInfos);
                }
            });
            roleResultList.addAll(newRoleInfo);

        }
        return roleResultList;
    }

    /**
     * url: /corpApi/organization/role/addOrUpdate
     * http://10.5.119.87:9526/project/494/interface/api/11808
     */
    @PostMapping("/addOrUpdate")
    @Transactional
    @OperateLog
    public JSONResult<?> addOrUpdate(@RequestBody RoleInfo roleInfo, BaseUserInfo bui) {
        if (!bui.getBgUser() && BooleanUtils.isTrue(roleInfo.getIsBackground())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.USER_DONT_ADD_ROLE);
        }
        log.info("RoleInfo:"+JsonUtils.toJsonString(roleInfo));
        if (Objects.equals(roleInfo.getLevel(), 1)) {
            if (Objects.nonNull(roleInfo.getParentId())) {
                roleInfo.setParentId(null);
            }
            //一级角色没有权限配置
            MbRole role = new MbRole();
            BeanUtils.copyProperties(roleInfo, role);
            role.setOrgId(roleInfo.getOrgId());
            //修改角色信息
            roleService.insertOrUpdate(role);
            rolePermissionService.clearLeft(Collections.singleton(role.getId()));
            rolePermissionService.batchAssociate(Collections.singleton(role.getId()), new HashSet<>(roleInfo.getPermissionList()));
            // 角色权限缓存刷新
            rolePermissionService.refreshRolePermissionCache(role.getId(), roleInfo.getPermissionList());
        } else if (Objects.equals(roleInfo.getLevel(), 2)){
            //二级角色
            if (roleInfo.getId() != null) {
                MbRole role = roleService.load(roleInfo.getId());
                if (Objects.isNull(role)) {
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.ROLE_INFO_NULL);
                }
                if (BooleanUtils.isTrue(role.getIsSystem())) {
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.SYSTEM_DONT_UPDATE);
                }
                if (BooleanUtils.isTrue(role.getIsDeleted())) {
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.ROLE_DEL_DONT_UPDATE);
                }
            }

            MbRole role = new MbRole();
            BeanUtils.copyProperties(roleInfo, role);
            role.setOrgId(roleInfo.getOrgId());
            //修改角色信息
            roleService.insertOrUpdate(role);
            //二级角色不存菜单权限-取一级角色的菜单权限
            List<MbRolePermission> parentRolePermissions = rolePermissionService.listRolePermission(role.getParentId());
            rolePermissionService.refreshRolePermissionCache(role.getId(), Optional.ofNullable(parentRolePermissions).orElse(Collections.emptyList()).stream().map(MbRolePermission::getPermissionId).collect(Collectors.toList()));
            //数据权限
            mbRoleResourceService.addOrUpdateInfo(role.getId(), Optional.ofNullable(roleInfo.getOrgIdList()).orElse(new ArrayList<>()), ResourceEnum.DEPT);
            //数据权限
            mbRoleResourceService.addOrUpdateInfo(role.getId(), Optional.ofNullable(roleInfo.getInvoicingOrgIdList()).orElse(new ArrayList<>()), ResourceEnum.INVOICING);
            bui.setRoleId(role.getId());
            //ResourceInfo resourceData = roleResourceService.getResourceData(role.getId());
            //JSONResult<ResourceInfo> userResourceData = permissionClient.findUserResourceData(bui);
           // manager.setResource(String.valueOf(role.getId()), resourceData);
            roleResourceManagerExt.delResource(String.valueOf(role.getId()));
            //数据权限菜单
            mbRoleResourceService.addOrUpdatePermissionInfo(role.getId(), Optional.ofNullable(roleInfo.getDataPermissionList()).orElse(new ArrayList<>()));
        } else {
            //运营管理角色
            if (roleInfo.getId() != null) {
                MbRole role = roleService.load(roleInfo.getId());
                if (Objects.isNull(role)) {
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.ROLE_INFO_NULL);
                }
                if (BooleanUtils.isTrue(role.getIsSystem())) {
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.SYSTEM_DONT_UPDATE);
                }
                if (BooleanUtils.isTrue(role.getIsDeleted())) {
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.ROLE_DEL_DONT_UPDATE);
                }
            }

            MbRole role = new MbRole();
            BeanUtils.copyProperties(roleInfo, role);
            role.setOrgId(bui.getBgUser() ? roleInfo.getOrgId() : bui.getCorpId());
            //修改角色信息
            roleService.insertOrUpdate(role);
            rolePermissionService.clearLeft(Collections.singleton(role.getId()));
            rolePermissionService.batchAssociate(Collections.singleton(role.getId()), new HashSet<>(roleInfo.getPermissionList()));
            // 角色权限缓存刷新
            rolePermissionService.refreshRolePermissionCache(role.getId(), roleInfo.getPermissionList());
            //数据权限
            mbRoleResourceService.addOrUpdateInfo(role.getId(), Optional.ofNullable(roleInfo.getOrgIdList()).orElse(new ArrayList<>()), ResourceEnum.DEPT);
            //数据权限
            mbRoleResourceService.addOrUpdateInfo(role.getId(), Optional.ofNullable(roleInfo.getInvoicingOrgIdList()).orElse(new ArrayList<>()), ResourceEnum.INVOICING);
            bui.setRoleId(role.getId());
            //JSONResult<ResourceInfo> userResourceData = permissionClient.findUserResourceData(bui);
            ResourceInfo resourceData = roleResourceService.getResourceData(role.getId());
            manager.setResource(String.valueOf(role.getId()), resourceData);
            //数据权限菜单
            mbRoleResourceService.addOrUpdatePermissionInfo(role.getId(), Optional.ofNullable(roleInfo.getDataPermissionList()).orElse(new ArrayList<>()));
        }

        return JSONResult.ok();
    }

    /**
     * url: /corpApi/organization/role/getRoleDetail
     * http://10.5.119.87:9526/project/494/interface/api/12008
     */
    @PostMapping("getRoleDetail")
    public JSONResult<RoleInfo> getRoleDetail(@RequestBody @Valid RoleId roleId, BaseUserInfo bui) throws IllegalAccessException {
        List<MbRolePermission> rolePermissions = rolePermissionService.listRolePermission(roleId.getId());
        if (CollectionUtils.isEmpty(rolePermissions)) {
            return JSONResult.ok();
        }
        MbRole mbRole = roleService.load(roleId.getId());
        if (mbRole == null) {
            return JSONResult.ok();
        }
        MbRolePermission rolePermission = rolePermissions.get(0);
        if (!bui.getBgUser() && StringUtils.isBlank(rolePermission.getRoleOrgId())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.USER_DONT_SELECT_ROLE);
        }
        RoleInfo roleInfo = new RoleInfo();
        roleInfo.setPermissionList(rolePermissions.stream().map(MbRolePermission::getPermissionId).filter(Objects::nonNull).collect(Collectors.toList()));
        roleInfo.setOrgIdList(Lists.newArrayList());
        roleInfo.setId(mbRole.getId());
        roleInfo.setDescription(mbRole.getDescription());
        roleInfo.setName(mbRole.getName());
        roleInfo.setIsRecManager(mbRole.getIsRecManager());
        roleInfo.setLevel(mbRole.getLevel());
        roleInfo.setParentId(mbRole.getParentId());
        if (Objects.nonNull(mbRole.getParentId()) && mbRole.getParentId() > 0) {
            MbRole parentRole = roleService.load(mbRole.getParentId());
            roleInfo.setParentName(parentRole.getName());
            List<MbRolePermission> parentRolePermissions = rolePermissionService.listRolePermission(mbRole.getParentId());
            roleInfo.setPermissionList(parentRolePermissions.stream().map(MbRolePermission::getPermissionId).filter(Objects::nonNull).collect(Collectors.toList()));
        }

        List<MbRoleResource> byRoleId = mbRoleResourceService.findByRoleId(roleId.getId());
        if (!CollectionUtils.isEmpty(byRoleId)) {
            JSONResult<List<OrgInfoVo>> invoiceList = organizationController.findByIdList(byRoleId.stream().filter(a -> Objects.equals(ResourceEnum.INVOICING.getCode(), a.getType()))
                    .map(MbRoleResource::getResourceId).map(String::valueOf).collect(Collectors.toList()));
            JSONResult<List<OrgInfoVo>> byOrgIdList = organizationController.findByIdList(byRoleId.stream().filter(a -> Objects.equals(ResourceEnum.DEPT.getCode(), a.getType()))
                    .map(MbRoleResource::getResourceId).map(String::valueOf).collect(Collectors.toList()));
            List<RoleDetailResponse.OrgInfo> submitterInfos = Optional.ofNullable(byOrgIdList.getData()).orElse(new ArrayList<>())
                    .stream().map(i -> new RoleDetailResponse.OrgInfo(i.getOrgId(), i.getName(), i.getOrgId(), i.getName(), i.getId())).collect(Collectors.toList());
            List<RoleDetailResponse.OrgInfo> invoiceInfo = Optional.ofNullable(invoiceList.getData()).orElse(new ArrayList<>())
                    .stream().map(i -> new RoleDetailResponse.OrgInfo(i.getOrgId(), i.getName(), i.getOrgId(), i.getName(), i.getId())).collect(Collectors.toList());
            roleInfo.setDataResourceRest(submitterInfos);
            roleInfo.setInvoicingResourceList(invoiceInfo);
            roleInfo.setDataPermissionList(byRoleId.stream().filter(a -> Objects.equals(ResourceEnum.PERMISSION.getCode(), a.getType())).map(MbRoleResource::getResourceId).collect(Collectors.toList()));
        }
        return JSONResult.success(roleInfo);
    }

    /**
     * url: /corpApi/organization/role/delete
     * http://10.5.119.87:9526/project/494/interface/api/11812
     */
    @PostMapping("/delete")
    @Transactional
    @OperateLog(OperateLogContant.ROLE_DELETE_SIGN)
    public JSONResult<?> delete(@RequestBody @Valid RoleId roleId, BaseUserInfo bui) throws IllegalAccessException {
        MbRole role = roleService.load(roleId.getId());
        if (BooleanUtils.isTrue(role.getIsSystem())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SYSTEM_DONT_UPDATE);
        }
        if (BooleanUtils.isNotTrue(bui.getBgUser()) && StringUtils.isBlank(role.getOrgId())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.USER_DONT_DEL_ROLE);
        }
        List<Long> delRoleIdList = new ArrayList<>();
        delRoleIdList.add(role.getId());
        if (Objects.isNull(role.getParentId()) || role.getParentId() == 0) {
            List<MbRole> mbRoles = roleService.selectByParentId(roleId.getId());
            delRoleIdList.addAll(mbRoles.stream().map(MbRole::getId).collect(Collectors.toList()));
        }

        for (Long id : delRoleIdList) {
            roleService.delete(id);
            userRoleService.clearRight(BaseUtils.buildSet(id));
            rolePermissionService.clearLeft(BaseUtils.buildSet(id));
        }
        return JSONResult.ok();
    }

    /**
     * http://10.5.119.87:9526/project/494/interface/api/12322
     */
    @PostMapping("/getRoles")
    public JSONResult<?> getRoles(@RequestBody @Valid CorpId id) {
        MbOrgInfo corpInfo = organizationInfoService.findRecentCompanyIdByOrgId(id.getCorpId());
        if (corpInfo == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.CORP_ID_ERROR);
        }
        return JSONResult.success(roleService.listCorpRoles(corpInfo.getOrgId())
                .stream()
                .map(r -> {
                    Map<Object, Object> map = new HashMap<>();
                    map.put("value", r.getId());
                    map.put("label", r.getName());
                    return map;
                })
                .collect(Collectors.toList()));
    }

    @PostMapping("/acquireBaseUserInfo")
    public JSONResult<BaseUserInfo> acquireBaseUserInfo(BaseUserInfo bui) {
        return JSONResult.success(bui);
    }

    /**
     * 查询对账管理员信息
     *
     * @param request
     * @return
     */
    @PostMapping("/searchRecManager")
    public JSONResult<SearchRecManagerResponseBO> searchRecManager(@RequestBody SearchRecManagerRequestBO request) {
        return JSONResult.success(roleService.searchRecManager(request));
    }

    /**
     * 查询对账管理员信息
     *
     * @param request
     * @return
     */
    @PostMapping("/newSearchRecManager")
    public JSONResult<SearchRecManagerResponseBO> newSearchRecManager(@RequestBody SearchRecManagerRequestBO request) {
        return JSONResult.success(roleService.newSearchRecManager(request));
    }

    @RequestMapping("/getPermission")
    public JSONResult<Permission> getPermission(@RequestBody DownloadRoleInfoRequest request, BaseUserInfo baseUserInfo) {
        Permission result = new Permission();
        Long roleId = null;
        //菜单权限在父级节点
        MbRole load = roleService.load(Long.valueOf(request.getRoleId()));
        if (Objects.nonNull(load.getParentId()) && load.getParentId() > 0) {
            roleId = load.getParentId();
        } else {
            roleId = Long.valueOf(request.getRoleId());
        }
        List<MbRolePermission> rolePermissions = rolePermissionService.listRolePermission(roleId);
        if (!CollectionUtils.isEmpty(rolePermissions) && rolePermissions.size() > 0) {
            Map<Long, List<MbRolePermission>> permissionMap = rolePermissions.stream().filter(item -> Objects.nonNull(item.getPermissionId())).collect(Collectors.groupingBy(MbRolePermission::getPermissionId));
            List<UserMenuTo> userMenuList = null;
            if (BooleanUtils.isFalse(baseUserInfo.getBgUser())) {
                if (StringUtils.isBlank(BaseUtils.acquireOrgId(baseUserInfo))) {
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.GET_ORG_ID_NULL);
                }
                userMenuList = userSrv.getPermissions(baseUserInfo.getUid(), baseUserInfo.getOrgId(), false);
            } else {
                userMenuList = userSrv.getPermissions(null, null, StringUtils.isBlank(request.getCorpId()));
            }
            List<PermissionMenu> permissionMenuList = new ArrayList<>();
            userMenuList.forEach(item -> {
                Boolean isSelect = Boolean.FALSE;
                List<MbRolePermission> mbRoleResources = permissionMap.get(item.getId());
                if (!CollectionUtils.isEmpty(mbRoleResources) && mbRoleResources.size() > 0) {
                    isSelect = Boolean.TRUE;
                }
                if (!isSelect && !request.getIsGetAll()) {
                    return;
                }
                PermissionMenu permissionMenu = PermissionMenu.builder().id(item.getId()).title(item.getTitle()).type(item.getType()).key(item.getKey()).name(item.getName()).isSelect(isSelect).build();
                permissionMenu.setChildren(recursionPermissionMenu(permissionMap, item, request.getIsGetAll()));
                permissionMenuList.add(permissionMenu);
            });
            result.setPermissionList(permissionMenuList);
        }

        List<MbRoleResource> byRoleId = mbRoleResourceService.findByRoleId(Long.valueOf(request.getRoleId()));
        if (!CollectionUtils.isEmpty(byRoleId)) {
            JSONResult<List<OrgInfoVo>> byOrgIdList = organizationController.findByIdList(byRoleId.stream().filter(a -> Objects.equals(ResourceEnum.DEPT.getCode(), a.getType()))
                    .map(MbRoleResource::getResourceId).map(String::valueOf).collect(Collectors.toList()));

            List<RoleDetailResponse.OrgInfo> submitterInfos = Optional.ofNullable(byOrgIdList.getData()).orElse(new ArrayList<>())
                    .stream().map(i -> new RoleDetailResponse.OrgInfo(i.getOrgId(), i.getName(), i.getOrgId(), i.getName(), i.getId())).collect(Collectors.toList());
            result.setDataResourceRest(submitterInfos);

            List<PermissionMenu> dataPermissionMenuList = new ArrayList<>();
            Map<Long, List<MbRoleResource>> dataPermissionMap = byRoleId.stream().filter(a -> Objects.equals(ResourceEnum.PERMISSION.getCode(), a.getType())).collect(Collectors.groupingBy(MbRoleResource::getResourceId));
            List<UserMenuTo> userMenuToList = userSrv.findDataPermission();
            userMenuToList.forEach(item -> {
                Boolean isSelect = Boolean.FALSE;
                List<MbRoleResource> mbRoleResources = dataPermissionMap.get(item.getId());
                if (!CollectionUtils.isEmpty(mbRoleResources) && mbRoleResources.size() > 0) {
                    isSelect = Boolean.TRUE;
                }
                if (!isSelect && !request.getIsGetAll()) {
                    return;
                }
                PermissionMenu permissionMenu = PermissionMenu.builder().id(item.getId()).title(item.getTitle()).type(item.getType()).key(item.getKey()).name(item.getName()).isSelect(isSelect).build();
                permissionMenu.setChildren(recursionDataPermissionMenu(dataPermissionMap, item, request.getIsGetAll()));
                dataPermissionMenuList.add(permissionMenu);
            });
            result.setDataPermissionList(dataPermissionMenuList);
        }
        return new JSONResult<>(result);
    }

    public List<PermissionMenu> recursionPermissionMenu(Map<Long, List<MbRolePermission>> permissionMap, UserMenuTo menuTo, Boolean isGetAll) {
        List<UserMenuTo> children = menuTo.getChildren();
        if (CollectionUtils.isEmpty(children)) {
            return new ArrayList<>();
        }
        List<PermissionMenu> dataPermissionMenuList = new ArrayList<>();
        children.forEach(item -> {
            Boolean isSelect = Boolean.FALSE;
            List<MbRolePermission> mbRolePermissionList = permissionMap.get(item.getId());
            if (!CollectionUtils.isEmpty(mbRolePermissionList) && mbRolePermissionList.size() > 0) {
                isSelect = Boolean.TRUE;
            }
            if (!isSelect && !isGetAll) {
                return;
            }
            PermissionMenu dataPermissionMenu = PermissionMenu.builder().id(item.getId()).title(item.getTitle()).type(item.getType()).key(item.getKey()).name(item.getName()).isSelect(isSelect).build();
            dataPermissionMenu.setChildren(recursionPermissionMenu(permissionMap, item, isGetAll));
            dataPermissionMenuList.add(dataPermissionMenu);
        });
        return dataPermissionMenuList;
    }

    public List<PermissionMenu> recursionDataPermissionMenu(Map<Long, List<MbRoleResource>> dataPermissionMap, UserMenuTo menuTo, Boolean isGetAll) {
        List<UserMenuTo> children = menuTo.getChildren();
        if (CollectionUtils.isEmpty(children)) {
            return new ArrayList<>();
        }
        List<PermissionMenu> dataPermissionMenuList = new ArrayList<>();
        children.forEach(item -> {
            Boolean isSelect = Boolean.FALSE;
            List<MbRoleResource> mbRoleResources = dataPermissionMap.get(item.getId());
            if (!CollectionUtils.isEmpty(mbRoleResources) && mbRoleResources.size() > 0) {
                isSelect = Boolean.TRUE;
            }
            if (!isSelect && !isGetAll) {
                return;
            }
            PermissionMenu dataPermissionMenu = PermissionMenu.builder().id(item.getId()).title(item.getTitle()).type(item.getType()).key(item.getKey()).name(item.getName()).isSelect(isSelect).build();
            dataPermissionMenu.setChildren(recursionDataPermissionMenu(dataPermissionMap, item, isGetAll));
            dataPermissionMenuList.add(dataPermissionMenu);
        });
        return dataPermissionMenuList;
    }

    @Data
    public static class Permission {

        //部门数据权限回显
        private List<RoleDetailResponse.OrgInfo> dataResourceRest;

        private List<PermissionMenu> permissionList;

        private List<PermissionMenu> dataPermissionList;
    }

    @Data
    @Builder
    public static class PermissionMenu {

        private Long id;
        private String title;
        private String type;
        private String key;
        private String name;
        private Boolean isSelect;
        private List<PermissionMenu> children;
    }

    @Data
    public static class CorpId {
        @NotBlank(message = "corpId不能为空。")
        private String corpId;
    }

    @Data
    public static class RoleId {
        @JsonProperty("roleId")
        @NotNull(message = "id 不能为空")
        private Long id;
    }

    @Data
    public static class RoleInfo {
        @JsonProperty("roleId")
        private Long id;
        @JsonProperty("label")
        private String name;
        private String roleName;
        @JsonProperty("count")
        private int userCount;
        @JsonProperty("roleDes")
        private String description;
        @JsonAlias("corpId")
        private String orgId;
        private List<Long> permissionList;

        private List<Long> orgIdList;
        private List<Long> invoicingOrgIdList;

        //菜单数据权限
        private List<Long> dataPermissionList;


        private Boolean isBackground;

        //部门数据权限回显
        private List<RoleDetailResponse.OrgInfo> dataResourceRest;

        private List<RoleDetailResponse.OrgInfo> invoicingResourceList;
        /**
         * 是否企服对账人
         */
        private Boolean isRecManager;

        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        private Date dataChangeTime;

        private Long parentId;
        private String parentName;
        //private List<Long> parentPermissionList;
        private Integer level;

        private List<RoleInfo> children;

        public void setName(String name) {
            this.roleName = this.name = name;
        }

        public void setRoleName(String name) {
            this.roleName = this.name = name;
        }
    }

    /**
     * 根据组织ID查询角色  根据角色获取到角色下的人的邮箱    pay服务--调用
     *
     * @param request
     * @return
     */
    @PostMapping("/findEailByOrgIds")
    public JSONResult<SearchRecManagerResponseBO> findEailByOrgIds(@RequestBody SearchRecManagerRequestBO request) {
        List<UserEmailDTO> userInfoByOrgIds = organizationEmployeeService.findUserInfoByOrgIds(request.getOrgIds());
        if (CollectionUtils.isEmpty(userInfoByOrgIds)) {
            return JSONResult.success(SearchRecManagerResponseBO.empty());
        }

        //根据邮件去重
        userInfoByOrgIds = userInfoByOrgIds.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() ->
                        new TreeSet<>(
                                Comparator.comparing(UserEmailDTO::getEmail)
                        )
                ), ArrayList::new
        ));

        Map<String, List<UserEmailDTO>> orgMap = userInfoByOrgIds.stream().filter(i -> StringUtils.isNotBlank(i.getEmail())).collect(Collectors.groupingBy(UserEmailDTO::getOrgId));

        if (CollectionUtils.isEmpty(orgMap)) {
            return JSONResult.success(SearchRecManagerResponseBO.empty());
        }

        Map<String, List<String>> orgEmailMap = Maps.newHashMap();
        orgMap.forEach((k, v) -> {
            orgEmailMap.put(k, v.stream().map(UserEmailDTO::getEmail).collect(Collectors.toList()));
        });

        return JSONResult.success(SearchRecManagerResponseBO.response(Lists.newArrayList(), orgEmailMap));
    }

    @PostMapping("/findUidByOrgIds")
    public JSONResult<SearchRecManagerResponseBO> findUidByOrgId(@RequestBody SearchRecManagerRequestBO request) {
        List<MbOrgEmployeeInfo> uidByOrgIds = organizationEmployeeService.findUidByOrgId(request.getOrgIds());
        if (CollectionUtils.isEmpty(uidByOrgIds)) {
            return JSONResult.success(SearchRecManagerResponseBO.empty());
        }
        //根据uid去重
        uidByOrgIds = uidByOrgIds.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(MbOrgEmployeeInfo::getUid))), ArrayList::new));
        List<RecManagerBO> recManagerBOS = employeeInfoConvert.convertToRecManger(uidByOrgIds);
        return JSONResult.success(SearchRecManagerResponseBO.create(recManagerBOS));
    }

    @RequestMapping("/downloadRole")
    public void downloadRole(@RequestBody DownloadRoleInfoRequest request, HttpServletResponse response) {
        List<UserRole> userRoleList = userRoleService.listRole(Lists.newArrayList(request.getCorpId()));
        if (CollectionUtils.isEmpty(userRoleList) || userRoleList.size() == 0) {
            userRoleList = new ArrayList<>();
        }
        if (StringUtils.isNotBlank(request.getRoleId())) {
            userRoleList = userRoleList.stream().filter(item -> Objects.equals(request.getRoleId(), item.getRoleId().toString())).collect(Collectors.toList());
        }
        log.info("roleList ：{}", JsonUtils.toJsonString(userRoleList));
        List<DownloadRoleExcelVo> responseVos = new ArrayList<>();
        userRoleList.forEach(item -> {
            DownloadRoleExcelVo vo = new DownloadRoleExcelVo();
            vo.setName(item.getUserName());
            vo.setOrgName(item.getUserOrgName());
            vo.setRole(item.getRoleName());
            vo.setEmail(item.getEmpEmail());
            vo.setPhone(item.getMobilePhone());
            responseVos.add(vo);
        });
        String fileName = "导出人员信息";
        ExcelPostEnum excelPostEnum = ExcelPostEnum.xlsx;
        ExcelCreateVO<DownloadRoleExcelVo> vo = ExcelCreateVO.<DownloadRoleExcelVo>builder()
                .fileName(fileName)
                .dataList(responseVos)
                .postfix(excelPostEnum)
                .cls(DownloadRoleExcelVo.class)
                .build();
        excelUtils.downloadExcelDocument(response, vo);
    }

    /**
     * 待优化查询存在效率问题
     *
     * @param request
     * @param baseUserInfo
     * @param response
     */
    @RequestMapping("/downloadRolePermission")
    public void downloadRolePermission(@RequestBody DownloadRoleInfoRequest request, BaseUserInfo baseUserInfo, HttpServletResponse response) {
        List<MbRole> userRoleList = roleService.listCorpRoles(request.getCorpId());
        if (CollectionUtils.isEmpty(userRoleList) || userRoleList.size() == 0) {
            userRoleList = new ArrayList<>();
        }
        if (StringUtils.isNotBlank(request.getRoleId())) {
            userRoleList = userRoleList.stream().filter(item -> Objects.equals(request.getRoleId(), item.getId().toString())).collect(Collectors.toList());
        }

        List<UserMenuTo> userMenuList = null;
        if (BooleanUtils.isFalse(baseUserInfo.getBgUser())) {
            if (StringUtils.isBlank(BaseUtils.acquireOrgId(baseUserInfo))) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.GET_ORG_ID_NULL);
            }
            userMenuList = userSrv.getPermissions(baseUserInfo.getUid(), baseUserInfo.getOrgId(), false);
        } else {
            userMenuList = userSrv.getPermissions(null, null, StringUtils.isBlank(request.getCorpId()));
        }
        log.info("userMenuList:{}", JsonUtils.toJsonString(userMenuList));

        List<DownloadRolePermissionExcelVo> permissionExcelVoList = new ArrayList<>();
        List<DownloadRoleDataPermissionExcelVo> dataPermissionExcelVoList = new ArrayList<>();

        List<MbRole> parentRoleList = userRoleList.stream().filter(role -> Objects.isNull(role.getParentId()) || role.getParentId() == 0).collect(Collectors.toList());
        Set<Long> parentIdSet = new HashSet<>();
        for (MbRole role : parentRoleList) {
            parentIdSet.add(role.getId());
            assemblePermissionExcel(role.getOrgId(), role.getId(), baseUserInfo, permissionExcelVoList, userMenuList);

            List<MbRole> dataRoleList = roleService.selectByParentId(role.getId());
            for (MbRole dataRole : dataRoleList) {
                assembleDataPermissionExcel(dataRole.getOrgId(), dataRole.getId(), baseUserInfo, dataPermissionExcelVoList);
            }
        }

        List<MbRole> roleList = userRoleList.stream().filter(role -> Objects.nonNull(role.getParentId()) && role.getParentId() > 0).collect(Collectors.toList());
        for (MbRole role : roleList) {
            if (parentIdSet.contains(role.getParentId())) {
                continue;
            }
            parentIdSet.add(role.getParentId());
            assemblePermissionExcel(role.getOrgId(), role.getParentId(), baseUserInfo, permissionExcelVoList, userMenuList);
            assembleDataPermissionExcel(role.getOrgId(), role.getId(), baseUserInfo, dataPermissionExcelVoList);
        }

        DownloadRolePermissionTemplateVo vo = new DownloadRolePermissionTemplateVo();
        vo.setRoleDataPermissionExcelVoList(dataPermissionExcelVoList);
        vo.setRolePermissionExcelVoList(permissionExcelVoList);
        vo.setFileName("导出角色信息");
        excelUtils.downloadExcelRolePermission(response, vo);
    }

    public void assemblePermissionExcel(String orgId, Long roleId, BaseUserInfo baseUserInfo, List<DownloadRolePermissionExcelVo> permissionExcelVoList, List<UserMenuTo> userMenuList) {
        List<MbRolePermission> rolePermissions = rolePermissionService.listRolePermission(roleId);
        if (CollectionUtils.isEmpty(rolePermissions)) {
            return;
        }
        Map<Long, List<MbRolePermission>> permissionMap = rolePermissions.stream().filter(item -> Objects.nonNull(item.getPermissionId())).collect(Collectors.groupingBy(MbRolePermission::getPermissionId));
        List<PermissionMenu> permissionMenuList = new ArrayList<>();
        userMenuList.forEach(item -> {
            Boolean isSelect = Boolean.FALSE;
            List<MbRolePermission> mbRoleResources = permissionMap.get(item.getId());
            if (!CollectionUtils.isEmpty(mbRoleResources) && mbRoleResources.size() > 0) {
                isSelect = Boolean.TRUE;
            }
            if (!isSelect && !false) {
                return;
            }
            PermissionMenu permissionMenu = PermissionMenu.builder().id(item.getId()).title(item.getTitle()).type(item.getType()).key(item.getKey()).name(item.getName()).isSelect(isSelect).build();
            permissionMenu.setChildren(recursionPermissionMenu(permissionMap, item, false));
            permissionMenuList.add(permissionMenu);
        });
        Map<String, String> permissionLinkedMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(permissionMenuList)) {
            permissionMenuList.forEach(item -> {
                if (!item.getIsSelect()) {
                    return;
                }
                String key = item.getTitle();
                permissionLinkedMap.put(key, "占位符");
                recursionRolePermissionExcel(item.getChildren(), permissionLinkedMap, key);
            });
        }
        MbRole load = roleService.load(roleId);
        permissionLinkedMap.forEach((key, value) -> {
            String[] nameArr = key.split("_");
            DownloadRolePermissionExcelVo excelVo = new DownloadRolePermissionExcelVo();
            for (int i = 0; i < nameArr.length; i++) {
                switch (i) {
                    case 0:
                        excelVo.setLevel1(nameArr[0]);
                        break;
                    case 1:
                        excelVo.setLevel2(nameArr[1]);
                        break;
                    case 2:
                        excelVo.setLevel3(nameArr[1]);
                        break;
                    case 3:
                        excelVo.setLevel4(nameArr[1]);
                        break;
                    default:
                        throw new CorpBusinessException(ExceptionCodeEnum.Alert, "需要增加Excel导出菜单节点");
                }
            }
            excelVo.setRoleName(load.getName());
            permissionExcelVoList.add(excelVo);
        });
    }

    public void assembleDataPermissionExcel(String orgId, Long roleId, BaseUserInfo baseUserInfo, List<DownloadRoleDataPermissionExcelVo> dataPermissionExcelVoList) {

        List<MbRoleResource> byRoleId = mbRoleResourceService.findByRoleId(roleId);
        if (CollectionUtils.isEmpty(byRoleId)) {
            return;
        }

        JSONResult<List<OrgInfoVo>> byOrgIdList = organizationController.findByIdList(byRoleId.stream().filter(a -> Objects.equals(ResourceEnum.DEPT.getCode(), a.getType()))
                .map(MbRoleResource::getResourceId).map(String::valueOf).collect(Collectors.toList()));

        List<RoleDetailResponse.OrgInfo> submitterInfos = Optional.ofNullable(byOrgIdList.getData()).orElse(new ArrayList<>())
                .stream().map(i -> new RoleDetailResponse.OrgInfo(i.getOrgId(), i.getName(), i.getOrgId(), i.getName(), i.getId())).collect(Collectors.toList());

        List<PermissionMenu> dataPermissionMenuList = new ArrayList<>();
        Map<Long, List<MbRoleResource>> dataPermissionMap = byRoleId.stream().filter(a -> Objects.equals(ResourceEnum.PERMISSION.getCode(), a.getType())).collect(Collectors.groupingBy(MbRoleResource::getResourceId));
        List<UserMenuTo> userMenuToList = userSrv.findDataPermission();
        userMenuToList.forEach(item -> {
            Boolean isSelect = Boolean.FALSE;
            List<MbRoleResource> mbRoleResources = dataPermissionMap.get(item.getId());
            if (!CollectionUtils.isEmpty(mbRoleResources) && mbRoleResources.size() > 0) {
                isSelect = Boolean.TRUE;
            }
            if (!isSelect && !false) {
                return;
            }
            PermissionMenu permissionMenu = PermissionMenu.builder().id(item.getId()).title(item.getTitle()).type(item.getType()).key(item.getKey()).name(item.getName()).isSelect(isSelect).build();
            permissionMenu.setChildren(recursionDataPermissionMenu(dataPermissionMap, item, false));
            dataPermissionMenuList.add(permissionMenu);
        });


        Map<String, String> dataPermissionLinkedMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(dataPermissionMenuList)) {
            dataPermissionMenuList.forEach(item -> {
                if (!item.getIsSelect()) {
                    return;
                }
                String key = item.getTitle();
                dataPermissionLinkedMap.put(key, "占位符");
                recursionRolePermissionExcel(item.getChildren(), dataPermissionLinkedMap, key);
            });
        }
        String orgName = "";
        if (!CollectionUtils.isEmpty(submitterInfos)) {
            orgName = submitterInfos.stream().map(item -> item.getOrgName()).collect(Collectors.joining(","));
        }
        String finalOrgName = orgName;
        MbRole load = roleService.load(roleId);
        MbRole loadParent = roleService.load(load.getParentId());
        dataPermissionLinkedMap.forEach((key, value) -> {
            String[] nameArr = key.split("_");
            DownloadRoleDataPermissionExcelVo excelVo = new DownloadRoleDataPermissionExcelVo();
            for (int i = 0; i < nameArr.length; i++) {
                switch (i) {
                    case 0:
                        excelVo.setLevel1(nameArr[0]);
                        break;
                    case 1:
                        excelVo.setLevel2(nameArr[1]);
                        break;
                    case 2:
                        excelVo.setLevel3(nameArr[1]);
                        break;
                    case 3:
                        excelVo.setLevel4(nameArr[1]);
                        break;
                    default:
                        throw new CorpBusinessException(ExceptionCodeEnum.Alert, "需要增加Excel导出菜单节点");
                }
            }
            excelVo.setRoleName(load.getName());
            excelVo.setOrgName(finalOrgName);
            excelVo.setParentName(loadParent.getName());
            dataPermissionExcelVoList.add(excelVo);
        });
    }

    public void recursionRolePermissionExcel(List<PermissionMenu> children, Map<String, String> permissionLinkedMap, String key) {
        if (CollectionUtils.isEmpty(children)) {
            return;
        }
        children.forEach(item -> {
            if (!item.getIsSelect()) {
                return;
            }
            //拆分key
            String newKey = key + "_" + item.getTitle();
            permissionLinkedMap.put(newKey, "占位符");
            permissionLinkedMap.remove(key);
            recursionRolePermissionExcel(item.getChildren(), permissionLinkedMap, newKey);
        });
    }

    @Deprecated
    @ApiOperation("角色数据权限关联菜单权限 -- 正常业务不可用")
    @PostMapping("/roleDataProcess")
    public void roleDataProcess(@RequestBody RoleInfo request) {
        mbRoleResourceService.roleDataProcess(request);
    }

}
